
import 'dart:async';
import 'package:flutter/services.dart';

typedef AdCallback = void Function({dynamic info});
typedef AdErrorCallback = void Function({dynamic error});

class KawaAd {
  static int _channelId = 0;
  static MethodChannel _methodChannel =
  new MethodChannel("com.mob.adsdk/method");

  /// set user id on login and logout
  static void setUserId(String userId) {
    _methodChannel.invokeMethod("setUserId", {"userId": userId});
  }

  static Future<dynamic> initSdk(String appId, String appKey){
    return _methodChannel.invokeMethod("initSdk",{
      "id":appId,
      "key":appKey,
    });
  }

  static void loadReward(String unitId,{AdCallback? onAdLoad,AdErrorCallback? onAdFail}){
    _methodChannel.invokeMethod("loadRewardVideoAd",{"_channelId": ++_channelId, "unitId": unitId});
    EventChannel eventChannel = EventChannel("com.mob.adsdk/event_$_channelId");
    eventChannel.receiveBroadcastStream().listen((event) {
      print(event);
      switch (event["name"]) {
        case "loaded":
          onAdLoad?.call();
          break;
        case "fail":
          onAdFail?.call();
          break;
      }
    });
  }

  /// show reward video ad
  static void showRewardVideoAd(
      {String? scene,
        AdCallback? onLoading,
        AdErrorCallback? onLoadFailed,
        AdCallback? onPlayStart,
        AdCallback? onPlayEnd,
        AdErrorCallback? onPlayFailed,
        AdCallback? onClosed,
        AdCallback? onReward,
        AdCallback? onClicked}) {
    _methodChannel.invokeMethod(
        "showRewardVideoAd", {"_channelId": ++_channelId, "scene": scene});

    EventChannel eventChannel = EventChannel("com.mob.adsdk/event_$_channelId");
    eventChannel.receiveBroadcastStream().listen((event) {
      print(event);
      switch (event["name"]) {
        case "loading":
          onLoading?.call();
          break;

        case "loadFail":
          onLoadFailed?.call();
          break;

        case "playStart":
          onPlayStart?.call(info: event["info"]);
          break;

        case "playEnd":
          onPlayEnd?.call(info: event["info"]);
          break;

        case "playFailed":
          onPlayFailed?.call(error: event["error"]);
          break;

        case "closed":
          onClosed?.call(info: event["info"]);
          break;

        case "click":
          onClicked?.call(info: event["info"]);
          break;

        case "reward":
          onReward?.call(info: event["info"]);
          break;
      }
    });
  }

  static void loadInters(String unitId,{AdCallback? onAdLoad,AdErrorCallback? onAdFail}){
    _methodChannel.invokeMethod("loadInterstitialAd",{"_channelId": ++_channelId, "unitId": unitId});
    EventChannel eventChannel = EventChannel("com.mob.adsdk/event_$_channelId");
    eventChannel.receiveBroadcastStream().listen((event) {
      print(event);
      switch (event["name"]) {
        case "loaded":
          onAdLoad?.call();
          break;
        case "fail":
          onAdFail?.call();
          break;
      }
    });
  }

  /// show interstitial ad
  static void showIntersAd(
      {
        String? scene,
        AdCallback? onLoading,
        AdErrorCallback? onLoadFailed,
        AdCallback? onShow,
        AdCallback? onClicked,
        AdCallback? onClosed,
        AdCallback? onVideoStart,
        AdCallback? onVideoEnd,
        AdErrorCallback? onError}) {
    _methodChannel.invokeMethod(
        "showInterstitialAd", {"_channelId": ++_channelId, "scene": scene});

    EventChannel eventChannel = EventChannel("com.mob.adsdk/event_$_channelId");
    eventChannel.receiveBroadcastStream().listen((event) {
      print(event);
      switch (event["name"]) {
        case "showLoading":
          onLoading?.call();
          break;

        case "showFail":
          onLoadFailed?.call();
          break;

        case "click":
          onClicked?.call(info: event["info"]);
          break;

        case "show":
          onShow?.call(info: event["info"]);
          break;

        case "close":
          onClosed?.call(info: event["info"]);
          break;

        case "start":
          onVideoStart?.call(info: event["info"]);
          break;

        case "videoEnd":
          onVideoEnd?.call(info: event["info"]);
          break;

        case "videoError":
          onError?.call(error: event["error"]);
          break;
      }
    });
  }

  static void loadSplash(String unitId,{AdCallback? onAdLoad,AdErrorCallback? onAdFail,AdErrorCallback? onAdLoadTimeout}){
    _methodChannel.invokeMethod("loadSplashAd",{"_channelId": ++_channelId, "unitId": unitId});
    EventChannel eventChannel = EventChannel("com.mob.adsdk/event_$_channelId");
    eventChannel.receiveBroadcastStream().listen((event) {
      print(event);
      switch (event["name"]) {
        case "loaded":
          onAdLoad?.call();
          break;
        case "fail":
          onAdFail?.call();
          break;
        case "timeout":
          onAdLoadTimeout?.call();
      }
    });
  }

  static void showSplashAd({
        String? scene,
        AdCallback? onLoading,
        AdErrorCallback? onLoadFailed,
        AdCallback? onShow,
        AdErrorCallback? onLoadTimeOut,
        AdCallback? onDismiss,
        AdCallback? onClick,
        AdErrorCallback? onError}) {
    _methodChannel.invokeMethod(
        "showSplashAd", {"_channelId": ++_channelId, "scene": scene});
    EventChannel eventChannel = EventChannel("com.mob.adsdk/event_$_channelId");
    eventChannel.receiveBroadcastStream().listen((event) {
      print(event);
      switch (event["name"]) {
        case "showLoading":
          onLoading?.call();
          break;

        case "showFail":
          onLoadFailed?.call();
          break;

        case "timeout":
          onLoadTimeOut?.call();
          break;

        case "show":
          onShow?.call(info: event["info"]);
          break;

        case "click":
          onClick?.call(info: event["info"]);
          break;

        case "dismiss":
          onDismiss?.call(info: event["info"]);
          break;
        case "fail":
          onError?.call(error: event["error"]);
          break;
      }
    });
  }
}
